home *** CD-ROM | disk | FTP | other *** search
- /*===========================================================================*
- * mpeg.c *
- * *
- * Procedures to generate the MPEG sequence *
- * *
- * EXPORTED PROCEDURES: *
- * SetFramePattern *
- * GetMPEGStream *
- * IncrementTCTime *
- * SetStatFileName *
- * SetGOPSize *
- * PrintStartStats *
- * *
- *===========================================================================*/
-
- /*
- * Copyright (c) 1993 The Regents of the University of California.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement is
- * hereby granted, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
- /*
- * $Header: /n/picasso/users/keving/encode/src/RCS/mpeg.c,v 1.6 1993/07/22 22:23:43 keving Exp keving $
- * $Log: mpeg.c,v $
- * Revision 1.6 1993/07/22 22:23:43 keving
- * nothing
- *
- * Revision 1.5 1993/06/30 20:06:09 keving
- * nothing
- *
- * Revision 1.4 1993/06/03 21:08:08 keving
- * nothing
- *
- * Revision 1.3 1993/02/19 18:10:12 keving
- * nothing
- *
- * Revision 1.2 1993/02/17 23:18:20 dwallach
- * checkin prior to keving's joining the project
- *
- */
-
-
- /*==============*
- * HEADER FILES *
- *==============*/
-
- #include "all.h"
- #include <time.h>
- #include <errno.h>
- #include "mtypes.h"
- #include "frames.h"
- #include "search.h"
- #include "mpeg.h"
- #ifdef OS2
- /* @@@ FAT 8.3 convention */
- #include "prototyp.h"
- #else
- #include "prototypes.h"
- #endif
- #include "parallel.h"
- #include "param.h"
- #ifdef OS2
- /* @@@ FAT 8.3 convention */
- #include "readfram.h"
- #else
- #include "readframe.h"
- #endif
- #include "fsize.h"
- #include "mheaders.h"
-
-
- /*===========*
- * CONSTANTS *
- *===========*/
-
- #define FRAMES_PER_SECOND 30
-
-
- /*==================*
- * STATIC VARIABLES *
- *==================*/
-
- static int32 diffTime;
- static int framesOutput;
- static int realStart, realEnd;
- static int currentGOP;
- static int timeMask;
- static int numI, numP, numB;
-
-
- /*==================*
- * GLOBAL VARIABLES *
- *==================*/
-
- extern int IOtime;
- int gopSize = 100; /* default */
- int32 tc_hrs, tc_min, tc_sec, tc_pict;
- int totalFramesSent;
- int yuvWidth, yuvHeight;
- int realWidth, realHeight;
- FrameTable *frameTable;
- char currentPath[MAXPATHLEN];
- char statFileName[256];
- time_t timeStart, timeEnd;
- FILE *statFile;
- char *framePattern;
- int framePatternLen;
- int referenceFrame;
-
-
- /*===============================*
- * INTERNAL PROCEDURE prototypes *
- *===============================*/
-
- static void ShowRemainingTime _ANSI_ARGS_((void));
- static void ComputeDHMSTime _ANSI_ARGS_((int32 someTime, char *timeText));
- static void ComputeGOPFrames _ANSI_ARGS_((int whichGOP, int *firstFrame,
- int *lastFrame, int numFrames));
- static void PrintEndStats _ANSI_ARGS_((int inputFrameBits, int32 totalBits));
- static void ComputeFrameTable _ANSI_ARGS_((void));
- static void ProcessRefFrame _ANSI_ARGS_((FrameTable *entry,
- BitBucket *bb, int lastFrame,
- char *outputFileName));
-
-
- /*=====================*
- * EXPORTED PROCEDURES *
- *=====================*/
-
- /*===========================================================================*
- *
- * SetReferenceFrameType
- *
- * set the reference frame type to be original or decoded
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: referenceFrame
- *
- *===========================================================================*/
- void
- SetReferenceFrameType(type)
- char *type;
- {
- if ( strcmp(type, "ORIGINAL") == 0 ) {
- referenceFrame = ORIGINAL_FRAME;
- } else if ( strcmp(type, "DECODED") == 0 ) {
- referenceFrame = DECODED_FRAME;
- } else {
- fprintf(stderr, "ERROR: Illegal reference frame type: '%s'\n",
- type);
- exit(1);
- }
- }
-
-
- /*===========================================================================*
- *
- * SetFramePattern
- *
- * set the IPB pattern; calls ComputeFrameTable to set up table
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: framePattern, framePatternLen, frameTable
- *
- *===========================================================================*/
- void
- SetFramePattern(pattern)
- char *pattern;
- {
- int len = strlen(pattern);
- char *buf;
- int index;
-
- if ( ! pattern ) {
- fprintf(stderr, "pattern cannot be NULL\n");
- exit(1);
- }
-
- if ( pattern[0] != 'i' && pattern[0] != 'I' ) {
- fprintf(stderr, "first frame must be 'i'\n");
- exit(1);
- }
-
- buf = (char *)malloc(sizeof(char)*(len+1));
- ERRCHK(buf, "malloc");
-
- for ( index = 0; index < len; index++ ) {
- switch( pattern[index] ) {
- case 'i': case 'I': buf[index] = 'i'; break;
- case 'p': case 'P': buf[index] = 'p'; break;
- case 'b': case 'B': buf[index] = 'b'; break;
- default:
- fprintf(stderr, "Frame type '%c' not supported.\n", pattern[index]);
- exit(1);
- }
- }
- buf[len] = 0;
-
- framePattern = buf;
- framePatternLen = len;
-
- ComputeFrameTable();
- }
-
-
- /*===========================================================================*
- *
- * GenMPEGStream
- *
- * generate an MPEG sequence stream (generally)
- * if whichGOP == frameStart == -1 then does complete MPEG sequence
- * if whichGOP != -1 then does numbered GOP only (without sequence
- * header)
- * if frameStart != -1 then does numbered frames only (without any
- * sequence or GOP headers)
- *
- * RETURNS: amount of time it took
- *
- * SIDE EFFECTS: too numerous to mention
- *
- *===========================================================================*/
- int32
- GenMPEGStream(whichGOP, frameStart, frameEnd, numFrames, ofp, outputFileName)
- int whichGOP;
- int frameStart;
- int frameEnd;
- int numFrames;
- FILE *ofp;
- char *outputFileName;
- {
- BitBucket *bb;
- int i;
- char frameType;
- MpegFrame *frame;
- FrameTable *entry = NULL;
- int firstFrame, lastFrame;
- int inputFrameBits = 0;
- char inputFileName[1024];
- time_t tempTimeStart, tempTimeEnd;
-
- time(&timeStart);
-
- ResetIFrameStats();
- ResetPFrameStats();
- ResetBFrameStats();
-
- Fsize_Reset();
-
- framesOutput = 0;
-
- if ( childProcess && separateConversion ) {
- SetFileType(slaveConversion);
- } else {
- SetFileType(inputConversion);
- }
-
- if ( whichGOP != -1 ) {
- ComputeGOPFrames(whichGOP, &firstFrame, &lastFrame, numFrames);
-
- realStart = firstFrame;
- realEnd = lastFrame;
-
- if ( FRAME_TYPE(firstFrame) == 'b' ) {
- /* need to load in previous frame; call it an I frame */
- frame = Frame_New(firstFrame-1, 'i');
-
- time(&tempTimeStart);
-
- if ( (referenceFrame == DECODED_FRAME) &&
- childProcess ) {
- WaitForDecodedFrame(firstFrame);
-
- if ( remoteIO ) {
- GetRemoteDecodedRefFrame(frame, firstFrame-1);
- } else {
- ReadDecodedRefFrame(frame, firstFrame-1);
- }
- } else {
- if ( remoteIO ) {
- GetRemoteFrame(frame, firstFrame-1);
- } else {
- GetNthInputFileName(inputFileName, firstFrame-1);
-
- if ( childProcess && separateConversion ) {
- ReadFrame(frame, inputFileName, slaveConversion, TRUE);
- } else {
- ReadFrame(frame, inputFileName, inputConversion, TRUE);
- }
- }
- }
-
- time(&tempTimeEnd);
- IOtime += (tempTimeEnd-tempTimeStart);
-
- /* should put in the correct frameTable place */
- }
- } else if ( frameStart != -1 ) {
- if ( frameEnd > numFrames-1 ) {
- fprintf(stdout, "ERROR: Specified last frame is out of bounds\n");
- exit(1);
- }
-
- realStart = frameStart;
- realEnd = frameEnd;
-
- firstFrame = frameStart;
- lastFrame = frameEnd;
-
- /* if first frame is P or B, need to read in P or I frame before it */
- if ( FRAME_TYPE(firstFrame) != 'i' ) {
- entry = &(frameTable[firstFrame % framePatternLen]);
-
- firstFrame = firstFrame - (entry->number - entry->prev->number);
- }
-
- /* if last frame is B, need to read in P or I frame after it */
- if ( (FRAME_TYPE(lastFrame) == 'b') && (lastFrame != numFrames-1) ) {
- entry = &(frameTable[lastFrame % framePatternLen]);
-
- lastFrame = lastFrame + (entry->next->number - entry->number);
- }
-
- if ( lastFrame > numFrames-1 ) { /* can't go last frame! */
- lastFrame = numFrames-1;
- }
- } else {
- firstFrame = 0;
- lastFrame = numFrames-1;
-
- realStart = 0;
- realEnd = numFrames-1;
- }
-
- /* count number of I, P, and B frames */
- numI = 0; numP = 0; numB = 0;
- timeMask = 0;
- for ( i = firstFrame; i <= lastFrame; i++ ) {
- frameType = FRAME_TYPE(i);
- switch(frameType) {
- case 'i': numI++; timeMask |= 0x1; break;
- case 'p': numP++; timeMask |= 0x2; break;
- case 'b': numB++; timeMask |= 0x4; break;
- }
- }
-
- if ( ! childProcess ) {
- PrintStartStats(realStart, realEnd);
- }
-
- if ( frameStart == -1 ) {
- bb = Bitio_New(ofp);
- } else {
- bb = NULL;
- }
-
- tc_hrs = 0; tc_min = 0; tc_sec = 0; tc_pict = 0;
- for ( i = 0; i < firstFrame; i++ ) {
- IncrementTCTime();
- }
-
- totalFramesSent = firstFrame;
- currentGOP = gopSize; /* so first I-frame generates GOP Header */
-
- #ifdef BLEAH
- fprintf(stdout, "firstFrame, lastFrame = %d, %d; real = %d, %d\n",
- firstFrame, lastFrame, realStart, realEnd);
- fflush(stdout);
- #endif
-
- for ( i = firstFrame; i <= lastFrame; i++) {
- frameType = FRAME_TYPE(i);
-
- /* skip non-reference frames */
- if ( frameType == 'b' ) {
- continue;
- }
-
- frame = Frame_New(i, frameType);
- if ( (i != firstFrame) && ((i % framePatternLen) == 0) ) {
- entry = &(frameTable[framePatternLen]);
- } else {
- entry = &(frameTable[i % framePatternLen]);
- }
-
- entry->frame = frame;
-
- time(&tempTimeStart);
-
- if ( (referenceFrame == DECODED_FRAME) &&
- ((i < realStart) || (i > realEnd)) ) {
- WaitForDecodedFrame(i);
-
- if ( remoteIO ) {
- GetRemoteDecodedRefFrame(frame, i);
- } else {
- ReadDecodedRefFrame(frame, i);
- }
- } else {
- if ( remoteIO ) {
- GetRemoteFrame(frame, i);
- } else {
- GetNthInputFileName(inputFileName, i);
- if ( childProcess && separateConversion ) {
- ReadFrame(frame, inputFileName, slaveConversion, TRUE);
- } else {
- ReadFrame(frame, inputFileName, inputConversion, TRUE);
- }
- }
- }
-
- time(&tempTimeEnd);
- IOtime += (tempTimeEnd-tempTimeStart);
-
- if ( i == firstFrame ) {
- inputFrameBits = 24*Fsize_x*Fsize_y;
- SetBlocksPerSlice();
-
- if ( (whichGOP == -1) && (frameStart == -1) ) {
- DBG_PRINT(("Generating sequence header\n"));
- Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ 1,
- /* pict_rate */ -1, /* bit_rate */ -1,
- /* buf_size */ -1, /*c_param_flag */ 1,
- /* iq_matrix */ NULL, /* niq_matrix */ NULL,
- /* ext_data */ NULL, /* ext_data_size */ 0,
- /* user_data */ NULL, /* user_data_size */ 0);
- }
- }
-
- ProcessRefFrame(entry, bb, lastFrame, outputFileName);
-
- /* in case this is first frame of pattern sequence; put it
- back to 0 */
- if ( entry == &frameTable[framePatternLen]) {
- frameTable[0].frame = frame;
- }
- }
-
- if ( entry->frame != NULL ) {
- Frame_Free(entry->frame);
- }
-
- /* SEQUENCE END CODE */
- if ( (whichGOP == -1) && (frameStart == -1) ) {
- Mhead_GenSequenceEnder(bb);
- }
-
- if ( frameStart == -1 ) {
- Bitio_Flush(bb);
- fclose(ofp);
-
- time(&timeEnd);
- diffTime = (int32)(timeEnd-timeStart);
-
- if ( ! childProcess ) {
- PrintEndStats(inputFrameBits, bb->cumulativeBits);
- }
- } else {
- time(&timeEnd);
- diffTime = (int32)(timeEnd-timeStart);
-
- if ( ! childProcess ) {
- PrintEndStats(inputFrameBits, 1);
- }
- }
-
- if ( childProcess ) {
- NoteFrameDone(frameStart, frameEnd);
- }
-
- return diffTime;
- }
-
-
- /*===========================================================================*
- *
- * IncrementTCTime
- *
- * increment the tc time by one second (and update min, hrs if necessary)
- * also increments totalFramesSent
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: totalFramesSent, tc_pict, tc_sec, tc_min, tc_hrs
- *
- *===========================================================================*/
- void
- IncrementTCTime()
- {
- totalFramesSent++;
- tc_pict++;
- if ( tc_pict == FRAMES_PER_SECOND ) {
- tc_pict = 0;
- tc_sec++;
- if ( tc_sec == 60 ) {
- tc_sec = 0;
- tc_min++;
- if ( tc_min == 60 ) {
- tc_min = 0;
- tc_hrs++;
- }
- }
- }
- }
-
-
- /*===========================================================================*
- *
- * SetStatFileName
- *
- * set the statistics file name
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: statFileName
- *
- *===========================================================================*/
- void
- SetStatFileName(fileName)
- char *fileName;
- {
- strcpy(statFileName, fileName);
- }
-
-
- /*===========================================================================*
- *
- * SetGOPSize
- *
- * set the GOP size (frames per GOP)
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: gopSize
- *
- *===========================================================================*/
- void
- SetGOPSize(size)
- int size;
- {
- gopSize = size;
- }
-
-
- /*===========================================================================*
- *
- * PrintStartStats
- *
- * print out the starting statistics (stuff from the param file)
- * firstFrame, lastFrame represent the first, last frames to be
- * encoded
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: none
- *
- *===========================================================================*/
- void
- PrintStartStats(firstFrame, lastFrame)
- int firstFrame;
- int lastFrame;
- {
- FILE *fpointer;
- register int i;
- char inputFileName[1024];
-
- if ( statFileName[0] == '\0' ) {
- statFile = NULL;
- } else {
- statFile = fopen(statFileName, "a"); /* open for appending */
- if ( statFile == NULL ) {
- fprintf(stderr, "ERROR: Could not open stat file: %s\n", statFileName);
- fprintf(stderr, " Sending statistics to stdout only.\n");
- fprintf(stderr, "\n\n");
- } else {
- fprintf(stdout, "Appending statistics to file: %s\n", statFileName);
- fprintf(stdout, "\n\n");
- }
- }
-
- for ( i = 0; i < 2; i++ ) {
- if ( i == 0 ) {
- fpointer = stdout;
- } else if ( statFile != NULL ) {
- fpointer = statFile;
- } else {
- continue;
- }
-
- fprintf(fpointer, "MPEG ENCODER STATS\n");
- fprintf(fpointer, "------------------\n");
- fprintf(fpointer, "TIME STARTED: %s", ctime(&timeStart));
- if ( getenv("HOST") != NULL ) {
- fprintf(fpointer, "MACHINE: %s\n", getenv("HOST"));
- } else {
- fprintf(fpointer, "MACHINE: unknown\n");
- }
-
- if ( firstFrame == -1 ) {
- fprintf(fpointer, "OUTPUT: %s\n", outputFileName);
- } else {
- GetNthInputFileName(inputFileName, firstFrame);
- fprintf(fpointer, "FIRST FILE: %s/%s\n", currentPath, inputFileName);
- GetNthInputFileName(inputFileName, lastFrame);
- fprintf(fpointer, "LAST FILE: %s/%s\n", currentPath,
- inputFileName);
- }
- fprintf(fpointer, "PATTERN: %s\n", framePattern);
- fprintf(fpointer, "GOP_SIZE: %d\n", gopSize);
- fprintf(fpointer, "SLICES PER FRAME: %d\n", slicesPerFrame);
- fprintf(fpointer, "RANGE: +/-%d\n", searchRange/2);
- fprintf(fpointer, "FULL SEARCH: %d\n", pixelFullSearch);
- fprintf(fpointer, "PSEARCH: %s\n", PSearchName());
- fprintf(fpointer, "BSEARCH: %s\n", BSearchName());
- fprintf(fpointer, "QSCALE: %d %d %d\n", qscaleI,
- GetPQScale(), GetBQScale());
- if ( referenceFrame == DECODED_FRAME ) {
- fprintf(fpointer, "REFERENCE FRAME: DECODED\n");
- } else if ( referenceFrame == ORIGINAL_FRAME ) {
- fprintf(fpointer, "REFERENCE FRAME: ORIGINAL\n");
- } else {
- fprintf(stderr, "ERROR: Illegal referenceFrame!!!\n");
- exit(1);
- }
- }
-
- fprintf(stdout, "\n\n");
- }
-
-
- /*===========================================================================*
- *
- * NonLocalRefFrame
- *
- * decides if this frame can be referenced from a non-local process
- *
- * RETURNS: TRUE or FALSE
- *
- * SIDE EFFECTS: none
- *
- *===========================================================================*/
- boolean
- NonLocalRefFrame(id)
- int id;
- {
- int lastIPid;
- int nextIPid;
- FrameTable *entry = NULL;
-
- if ( ! childProcess ) {
- return FALSE;
- }
-
- if ( (id % framePatternLen) == 0 ) {
- entry = &frameTable[framePatternLen];
- } else {
- entry = &(frameTable[id % framePatternLen]);
- }
-
- if ( entry == NULL ) {
- fprintf(stdout, "ENTRY == NULL!!!\n");
- fflush(stdout);
- exit(1);
- }
-
- lastIPid = id - (entry->number - entry->prev->number);
-
- /* might be accessed by B-frame */
- if ( lastIPid+1 < realStart ) {
- return TRUE;
- }
-
- entry = &(frameTable[id % framePatternLen]);
-
- /* if B-frame is out of range, then current frame can be ref'd by it */
- nextIPid = id + (entry->next->number - entry->number);
-
- /* might be accessed by B-frame */
- if ( nextIPid-1 > realEnd ) {
- return TRUE;
- }
-
- /* might be accessed by P-frame */
- if ( (nextIPid > realEnd) && (FRAME_TYPE(nextIPid) == 'p') ) {
- return TRUE;
- }
-
- return FALSE;
- }
-
-
- /*=====================*
- * INTERNAL PROCEDURES *
- *=====================*/
-
- /*===========================================================================*
- *
- * ComputeDHMSTime
- *
- * turn some number of seconds (someTime) into a string which
- * summarizes that time according to scale (days, hours, minutes, or
- * seconds)
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: none
- *
- *===========================================================================*/
- static void
- ComputeDHMSTime(someTime, timeText)
- int32 someTime;
- char *timeText;
- {
- int days, hours, mins, secs;
-
- days = someTime / (24*60*60);
- someTime -= days*24*60*60;
- hours = someTime / (60*60);
- someTime -= hours*60*60;
- mins = someTime / 60;
- secs = someTime - mins*60;
-
- if ( days > 0 ) {
- sprintf(timeText, "Total time: %d days and %d hours", days, hours);
- } else if ( hours > 0 ) {
- sprintf(timeText, "Total time: %d hours and %d minutes", hours, mins);
- } else if ( mins > 0 ) {
- sprintf(timeText, "Total time: %d minutes and %d seconds", mins, secs);
- } else {
- sprintf(timeText, "Total time: %d seconds", secs);
- }
- }
-
-
- /*===========================================================================*
- *
- * ComputeGOPFrames
- *
- * calculate the first, last frames of the numbered GOP
- *
- * RETURNS: lastFrame, firstFrame changed
- *
- * SIDE EFFECTS: none
- *
- *===========================================================================*/
- static void
- ComputeGOPFrames(whichGOP, firstFrame, lastFrame, numFrames)
- int whichGOP;
- int *firstFrame;
- int *lastFrame;
- int numFrames;
- {
- int passedB;
- int currGOP;
- int gopNum, frameNum;
-
- /* calculate first, last frames of whichGOP GOP */
-
- *firstFrame = -1;
- *lastFrame = -1;
- gopNum = 0;
- frameNum = 0;
- passedB = 0;
- currGOP = 0;
- while ( *lastFrame == -1 ) {
- if ( frameNum >= numFrames ) {
- fprintf(stderr, "ERROR: There aren't that many GOPs!\n");
- exit(1);
- }
-
- fprintf(stdout, "GOP STARTS AT %d\n", frameNum-passedB);
-
- if ( gopNum == whichGOP ) {
- *firstFrame = frameNum-passedB;
- }
-
- /* go past one gop */
- while ( (frameNum < numFrames) &&
- ((FRAME_TYPE(frameNum) != 'i') || currGOP < gopSize) ) {
- currGOP += (1 + passedB);
-
- frameNum++;
-
- passedB = 0;
- while ( FRAME_TYPE(frameNum) == 'b' ) {
- frameNum++;
- passedB++;
- }
- }
-
- currGOP -= gopSize;
-
- if ( gopNum == whichGOP ) {
- *lastFrame = (frameNum-passedB-1);
- }
-
- fprintf(stdout, "GOP ENDS at %d\n", frameNum-passedB-1);
-
- gopNum++;
- }
- }
-
-
- /*===========================================================================*
- *
- * PrintEndStats
- *
- * print end statistics (summary, time information)
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: none
- *
- *===========================================================================*/
- static void
- PrintEndStats(inputFrameBits, totalBits)
- int inputFrameBits;
- int32 totalBits;
- {
- FILE *fpointer;
- register int i;
- char timeText[256];
-
- fprintf(stdout, "\n\n");
-
- ComputeDHMSTime(diffTime, timeText);
-
- for ( i = 0; i < 2; i++ ) {
- if ( i == 0 ) {
- fpointer = stdout;
- } else if ( statFile != NULL ) {
- fpointer = statFile;
- } else {
- continue;
- }
-
- fprintf(fpointer, "TIME COMPLETED: %s", ctime(&timeEnd));
- fprintf(fpointer, "%s\n\n", timeText);
-
- ShowIFrameSummary(inputFrameBits, totalBits, fpointer);
- ShowPFrameSummary(inputFrameBits, totalBits, fpointer);
- ShowBFrameSummary(inputFrameBits, totalBits, fpointer);
- fprintf(fpointer, "---------------------------------------------\n");
- fprintf(fpointer, "Total Compression: %3d:1\n",
- framesOutput*inputFrameBits/totalBits);
- fprintf(fpointer, "Total Frames Per Second: %f\n",
- (float)framesOutput/(float)diffTime);
- fprintf(fpointer, "Total Output Bit Rate (30 fps): %d bits/sec\n",
- 30*totalBits/framesOutput);
- fprintf(fpointer, "\n\n");
- }
-
- if ( statFile != NULL ) {
- fclose(statFile);
- }
- }
-
-
- /*===========================================================================*
- *
- * ComputeFrameTable
- *
- * compute a table of I, P, B frames to help in determining dependencies
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: frameTable
- *
- *===========================================================================*/
- static void
- ComputeFrameTable()
- {
- register int index;
- FrameTable *lastI, *lastIP, *firstB;
- FrameTable *ptr;
- int numberP, numberN, numberNO;
-
- frameTable = (FrameTable *) malloc((framePatternLen+1)*sizeof(FrameTable));
-
- lastI = NULL;
- lastIP = NULL;
- firstB = NULL;
- for ( index = 0; index < framePatternLen; index++ ) {
- frameTable[index].number = index;
- frameTable[index].freeNow = TRUE;
- frameTable[index].frame = NULL;
-
- switch( framePattern[index] ) {
- case 'i':
- ptr = firstB;
- while ( ptr != NULL ) {
- ptr->next = &(frameTable[index]);
- ptr = ptr->nextOutput;
- }
- frameTable[index].nextOutput = firstB;
- frameTable[index].prev = lastIP; /* for freeing */
- if ( lastIP != NULL ) {
- lastIP->next = &(frameTable[index]);
- }
- lastIP = &(frameTable[index]);
- firstB = NULL;
- break;
- case 'p':
- ptr = firstB;
- while ( ptr != NULL ) {
- ptr->next = &(frameTable[index]);
- ptr = ptr->nextOutput;
- }
- frameTable[index].nextOutput = firstB;
- frameTable[index].prev = lastIP;
- if ( lastIP != NULL ) {
- lastIP->next = &(frameTable[index]);
- }
- lastIP->freeNow = FALSE;
- lastIP = &(frameTable[index]);
- firstB = NULL;
- break;
- case 'b':
- if ( (index+1 == framePatternLen) ||
- (framePattern[index+1] != 'b') ) {
- frameTable[index].nextOutput = NULL;
- } else {
- frameTable[index].nextOutput = &(frameTable[index+1]);
- }
- frameTable[index].prev = lastIP;
- lastIP->freeNow = FALSE;
- if ( firstB == NULL ) {
- firstB = &(frameTable[index]);
- }
- break;
- }
- }
-
- frameTable[framePatternLen].number = framePatternLen;
- frameTable[framePatternLen].frame = NULL;
-
- ptr = firstB;
- while ( ptr != NULL ) {
- ptr->next = &(frameTable[framePatternLen]);
- ptr = ptr->nextOutput;
- }
- frameTable[framePatternLen].nextOutput = firstB;
- frameTable[framePatternLen].prev = lastIP;
- frameTable[framePatternLen].freeNow = frameTable[0].freeNow;
-
- frameTable[0].prev = lastIP;
- if ( lastIP != NULL ) {
- lastIP->next = &(frameTable[framePatternLen]);
- }
-
- for ( index = 0; index < framePatternLen+1; index++ ) {
- if ( frameTable[index].prev == NULL ) {
- numberP = -1;
- } else {
- numberP = frameTable[index].prev->number;
- }
-
- if ( frameTable[index].next == NULL ) {
- numberN = -1;
- } else {
- numberN = frameTable[index].next->number;
- }
-
- if ( frameTable[index].nextOutput == NULL ) {
- numberNO = -1;
- } else {
- numberNO = frameTable[index].nextOutput->number;
- }
- }
- }
-
-
- /*===========================================================================*
- *
- * ProcessRefFrame
- *
- * process an I or P frame -- encode it, and process any B frames that
- * we can now
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: stuff appended to bb
- *
- *===========================================================================*/
- static void
- ProcessRefFrame(entry, bb, lastFrame, outputFileName)
- FrameTable *entry;
- BitBucket *bb;
- int lastFrame;
- char *outputFileName;
- {
- FrameTable *ptr;
- char fileName[1024];
- char inputFileName[1024];
- FILE *fpointer = NULL;
- boolean separateFiles;
- int id;
- time_t tempTimeStart, tempTimeEnd;
-
- separateFiles = (bb == NULL);
-
- if ( separateFiles && (entry->frame->id >= realStart) &&
- (entry->frame->id <= realEnd) ) {
- if ( remoteIO ) {
- bb = Bitio_New(NULL);
- } else {
- sprintf(fileName, "%s.frame.%d", outputFileName, entry->frame->id);
- /* @@@ Open binary mode for OS/2, Andy Key */
- #ifdef OS2
- if ( (fpointer = fopen(fileName, "wb")) == NULL ) {
- #else
- if ( (fpointer = fopen(fileName, "w")) == NULL ) {
- #endif
- fprintf(stderr, "ERROR: Could not open output file: %s\n",
- fileName);
- exit(1);
- }
-
- bb = Bitio_New(fpointer);
- }
- }
-
- /* nothing to do */
- if ( entry->frame->id < realStart ) {
- return;
- }
-
- /* first, output this frame */
- if ( entry->frame->type == TYPE_IFRAME ) {
- /* only start a new GOP with I */
- /* don't start GOP if only doing frames */
- if ( (! separateFiles) && (currentGOP >= gopSize) ) {
- int closed;
-
- /* first, check to see if closed GOP */
- if ( totalFramesSent == entry->frame->id ) {
- closed = 1;
- } else {
- closed = 0;
- }
-
- fprintf(stdout, "Creating new GOP (closed = %d) before frame %d\n",
- closed, entry->frame->id);
-
- /* new GOP */
- Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0,
- tc_hrs, tc_min, tc_sec, tc_pict,
- closed, /* broken_link */ 0,
- /* ext_data */ NULL, /* ext_data_size */ 0,
- /* user_data */ NULL, /* user_data_size */ 0);
- currentGOP -= gopSize;
- SetGOPStartTime(entry->frame->id);
- }
-
- if ( (entry->frame->id >= realStart) && (entry->frame->id <= realEnd) ) {
- GenIFrame(bb, entry->frame);
- framesOutput++;
-
- if ( separateFiles ) {
- if ( remoteIO ) {
- SendRemoteFrame(entry->frame->id, bb);
- } else {
- Bitio_Flush(bb);
- fclose(fpointer);
- }
- }
- }
-
- numI--;
- timeMask &= 0x6;
-
- currentGOP++;
- IncrementTCTime();
- } else {
- if ( (entry->frame->id >= realStart) && (entry->frame->id <= realEnd) ) {
- GenPFrame(bb, entry->frame, entry->prev->frame);
- framesOutput++;
-
- if ( separateFiles ) {
- if ( remoteIO ) {
- SendRemoteFrame(entry->frame->id, bb);
- } else {
- Bitio_Flush(bb);
- fclose(fpointer);
- }
- }
- }
-
- numP--;
- timeMask &= 0x5;
- ShowRemainingTime();
-
- currentGOP++;
- IncrementTCTime();
- }
-
- /* now, follow nextOutput and output B-frames */
- ptr = entry->nextOutput;
- while ( ptr != NULL ) {
- id = entry->frame->id - (entry->number - ptr->number);
-
- if ( (id >= realStart) && (id <= realEnd) ) {
- ptr->frame = Frame_New(id, 'b');
-
- time(&tempTimeStart);
-
- /* read B frame, output it */
- if ( remoteIO ) {
- GetRemoteFrame(ptr->frame, ptr->frame->id);
- } else {
- GetNthInputFileName(inputFileName, id);
- if ( childProcess && separateConversion ) {
- ReadFrame(ptr->frame, inputFileName, slaveConversion, TRUE);
- } else {
- ReadFrame(ptr->frame, inputFileName, inputConversion, TRUE);
- }
- }
-
- time(&tempTimeEnd);
- IOtime += (tempTimeEnd-tempTimeStart);
-
- if ( separateFiles ) {
- if ( remoteIO ) {
- bb = Bitio_New(NULL);
- } else {
- sprintf(fileName, "%s.frame.%d", outputFileName, ptr->frame->id);
- /* @@@ Open binary mode for OS/2, Andy Key */
- #ifdef OS2
- if ( (fpointer = fopen(fileName, "wb")) == NULL ) {
- #else
- if ( (fpointer = fopen(fileName, "w")) == NULL ) {
- #endif
- fprintf(stderr, "ERROR: Could not open output file: %s\n",
- fileName);
- exit(1);
- }
- bb = Bitio_New(fpointer);
- }
- }
-
- GenBFrame(bb, ptr->frame, ptr->prev->frame, ptr->next->frame);
- framesOutput++;
-
- if ( separateFiles ) {
- if ( remoteIO ) {
- SendRemoteFrame(ptr->frame->id, bb);
- } else {
- Bitio_Flush(bb);
- fclose(fpointer);
- }
- }
-
- /* free this B frame right away */
- Frame_Free(ptr->frame);
- ptr->frame = NULL;
- }
-
- numB--;
- timeMask &= 0x3;
- ShowRemainingTime();
-
- currentGOP++;
- IncrementTCTime();
-
- ptr = ptr->nextOutput;
- }
-
- /* now free previous frame, if there was one */
- if ( (entry->frame->type != TYPE_IFRAME) ||
- (entry->nextOutput != NULL) ) {
- if ( entry->prev->frame != NULL ) {
- Frame_Free(entry->prev->frame);
- entry->prev->frame = NULL;
- }
- }
-
- /* check to see if we can free this frame now */
- if ( entry->freeNow || (entry->frame->id == lastFrame) ) {
- if ( entry->frame != NULL ) {
- Frame_Free(entry->frame);
- entry->frame = NULL;
- }
- }
-
- /* note, we may still not free last frame if lastFrame is incorrect
- (if the last frames are B frames, they aren't output!)
- */
- }
-
-
- /*===========================================================================*
- *
- * ShowRemainingTime
- *
- * print out an estimate of the time left to encode
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS: none
- *
- *===========================================================================*/
- static void
- ShowRemainingTime()
- {
- static int lastTime = 0;
- float timeI, timeP, timeB;
- float total;
-
- if ( childProcess ) {
- return /* nothing */;
- }
-
- if ( numI + numP + numB == 0 ) { /* no time left */
- return /* nothing */ ;
- }
-
- if ( timeMask != 0 ) { /* haven't encoded all types yet */
- return /* nothing */ ;
- }
-
- timeI = EstimateSecondsPerIFrame();
- timeP = EstimateSecondsPerPFrame();
- timeB = EstimateSecondsPerBFrame();
-
- total = (float)numI*timeI + (float)numP*timeP + (float)numB*timeB;
-
- if ( (quietTime >= 0) &&
- (((lastTime-(int)total) >= quietTime) || (lastTime == 0)) ) {
- if ( total > 270.0 ) {
- fprintf(stdout, "ESTIMATED TIME OF COMPLETION: %d minutes\n",
- ((int)total+30)/60);
- } else {
- fprintf(stdout, "ESTIMATED TIME OF COMPLETION: %d seconds\n",
- (int)total);
- }
-
- lastTime = (int)total;
- }
- }
-
-
- void
- ReadDecodedRefFrame(frame, frameNumber)
- MpegFrame *frame;
- int frameNumber;
- {
- FILE *fpointer;
- char fileName[256];
- int width, height;
- register int y;
-
- width = Fsize_x;
- height = Fsize_y;
-
- sprintf(fileName, "%s.decoded.%d", outputFileName, frameNumber);
- fprintf(stdout, "reading %s\n", fileName);
- fflush(stdout);
-
- /* @@@ Open binary mode for OS/2, Andy Key */
- #ifdef OS2
- fpointer = fopen(fileName, "rb");
- #else
- fpointer = fopen(fileName, "r");
- #endif
-
- Frame_AllocDecoded(frame, TRUE);
-
- for ( y = 0; y < height; y++ ) {
- fread(frame->decoded_y[y], 1, width, fpointer);
- }
-
- for (y = 0; y < height / 2; y++) { /* U */
- fread(frame->decoded_cb[y], 1, width / 2, fpointer);
- }
-
- for (y = 0; y < height / 2; y++) { /* V */
- fread(frame->decoded_cr[y], 1, width / 2, fpointer);
- }
-
- fclose(fpointer);
- }
-